from math import *
import re
from urllib import request
from urllib.parse import quote
from os.path import exists
from time import sleep

# City name, population lower bound and radius in meters
cities = [
  { 'name': 'Adana', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Algiers', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Almaty', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Amsterdam', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Ankara', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Athens', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Atlanta', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Baku', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Baltimore', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Bangalore', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Bangkok', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Barcelona', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Beijing', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Belo Horizonte', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Berlin', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Bilbao', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Boston', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Brescia', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Brussels', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Bucharest', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Budapest', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Buenos Aires', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Bursa', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Busan', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Cairo', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Caracas', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Catania', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Chengdu', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Chennai', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Chicago', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Chongqing', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Cleveland', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Copenhagen', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Daegu', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Daejeon', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Dalian', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Delhi', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Dnipropetrovsk', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Dubai', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Fortaleza', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Foshan', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Frankfurt', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Fukuoka', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Genoa', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Glasgow', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Guangzhou', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Gwangju', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Hamburg', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Hangzhou', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Harbin', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Helsinki', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Hiroshima', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Hong Kong', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Incheon', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Istanbul', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Izmir', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Kaohsiung', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Kazan', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Kharkiv', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Kiev', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Kobe', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Kolkata', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Kuala Lumpur', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Kunming', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Kyoto', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Lausanne', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Lille', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Lima', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Lisbon', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'London', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Los Angeles', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Los Teques', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Lyon', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Madrid', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Manila', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Maracaibo', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Marseille', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Mecca', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Mexico City', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Miami', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Milan', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Minsk', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Montreal', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Moscow', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Munich', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Nagoya', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Nanjing', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Naples', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'New York City', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Nizhny Novgorod', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Novosibirsk', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Nuremberg', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Osaka', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Oslo', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Palma de Mallorca', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Paris', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Philadelphia', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Porto Alegre', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Prague', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Pyongyang', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Recife', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Rennes', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Rio de Janeiro', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Rome', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Rotterdam', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Saint Petersburg', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Samara', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'San Francisco Bay Area', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'San Juan', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Santiago', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Santo Domingo', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Sapporo', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Sendai', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Seoul', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Seville', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Shanghai', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Shenyang', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Shenzhen', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Singapore', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Sofia', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Stockholm', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Suzhou', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Taipei', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Tashkent', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Tbilisi', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Tehran', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Teresina', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Tianjin', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Tokyo', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Toronto', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Toulouse', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Turin', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Vancouver', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Vienna', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Warsaw', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Wuhan', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Xi\'an', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Yekaterinburg', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Yerevan', 'minpopulation': 100000, 'radius': 25000 },
  { 'name': 'Yokohama', 'minpopulation': 100000, 'radius': 25000 },
]

overpassScript = open('get_maps.xml', 'r')
overpassTemplate = overpassScript.read()

successCount = 0
badCount = 0
skipCount = 0
errorCount = 0
totalCount = 0
for city in cities:
  totalCount += 1
  outpath = 'output/%s.xml' % city['name']
  badoutpath = outpath + '.bad'
  print(city['name'])
  if (exists(outpath)):
    print('  SKIPPING: %s exists already' % outpath)
    skipCount += 1
    continue
  if (exists(badoutpath)):
    print('  SKIPPING: %s exists already' % badoutpath)
    skipCount += 1
    continue

  # Fill in template with city properties
  minPopDigits = 1 + floor(log10(float(city['minpopulation'])))
  script = overpassTemplate
  script = script.replace("@NAME@", city['name'])
  script = script.replace("@MINPOPLOG@", str(minPopDigits))
  script = script.replace("@RADIUS@", str(city['radius']))
  
  # Escape script for use in URL
  script = re.sub('\>\s+', '>', script)
  script = quote(script)
  
  # Make request to Overpass API
  url = 'http://overpass-api.de/api/interpreter?data=%s'
  url = url % script
  try:
    response = request.urlopen(url)
    html = response.read()
  except:
    print('  ERROR: failed to perform GET request')
    errorCount += 1
    continue  
  sleep(3)
  
  # Calc some stats
  htmlstr = str(html)
  stationCount = htmlstr.count('<tag k="railway" v="station"/>')
  stationCount += htmlstr.count('<tag k="railway" v="halt"/>')
  lineCount = htmlstr.count('<tag k="railway" v="subway"/>')
  print('  %d stations' % stationCount)
  print('  %d lines' % lineCount)
  
  isBad = False
  if (stationCount == 0):
    isBad = True
    print('  BAD RESULT: no stations')
  elif (lineCount == 0):
    isBad = True
    print('  BAD RESULT: no lines')
    
  # Write result to file
  if (isBad):
    output = open(badoutpath, 'wb')
    badCount += 1
  else:
    output = open(outpath, 'wb')
    successCount += 1
  output.write(html)

# Print final result
print('All done! Here are some final stats:')
print('  Success:     %d' % successCount)
print('  Bad results: %d' % badCount)
print('  Skipped:     %d' % skipCount)
print('  Errors:      %d' % errorCount)
print('  Total:       %d' % totalCount)
